<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    
</head>
<body>
    <script>

        function Vue(options){
            this._data = options.data
            this._poroxy()
            this._defineReactive(this._data)
            this._initMethods(options.methods)
        }

        Vue.prototype = {

            _defineReactive(data){
                if(data == null || typeof data != 'object') return

                Object.keys(data).forEach((key)=>{
                    let value = data[key]

                    this._defineReactive(value)

                    Object.defineProperty(data,key,{
                        get(){
                            console.log(`监视到读取${key}属性`)
                            return value
                        },
                        set(val){
                            value = val
                            console.log(`监视到${key}属性更新为${val}`)
                            console.log('准备去更新DOM')
                        }
                    })
                })
            },

            _initMethods(methods){
                Object.keys(methods).forEach((key)=>{
                    this[key] = methods[key].bind(this)
                })
            },

            _poroxy(){
                Object.keys(this._data).forEach((key)=>{
                    Object.defineProperty(this,key,{
                        get(){
                            console.log('getter')
                            return this._data[key]
                        },
                        set(value){
                            console.log('setter')
                            this._data[key] = value
                        }
                    })
                })
            }
        }

   

    </script>

    <script>
    const vm = new Vue({
      data: {
        msg: 'abc',
        obj: {
          count: 2
        }
      },
      methods: {
        fn (){
          console.log('fn', this.msg)
        }
      }
    })


    console.log(vm.msg) // 内部监视到了读取data的属性
    
    vm.msg = 'cba' // 内部监视到了更新data的外层属性

    vm.obj.count = 3 // 内部监视到了更新data的内层属性
    </script>
</body>
</html>